home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr47 / ucrasm27.zip / TEST.ZIP / TS.ASM < prev    next >
Assembly Source File  |  1991-10-30  |  8KB  |  392 lines

  1. ;****************************************************************************
  2. ;
  3. ; TS:     A "Text Statistics" package which demonstrates the use of the UCR
  4. ;    Standard Library Package.
  5. ;
  6. ; Note:    The purpose of this program is not to demonstrate blazing fast
  7. ;    assembly code (it's not particularly fast) but rather to demonstrate
  8. ;    how easy it is to write assembly code using the standard library
  9. ;    and MASM 6.0.
  10. ;
  11. ; Randall Hyde
  12. ; 10/2/91
  13. ;
  14. ;***************************************************************************
  15. ;
  16. ;  The following include must be outside any segment and before the
  17. ;  ZZZZZZSEG segment.  It includes all the macro definitions for the
  18. ;  UCR Standard Library.
  19. ;
  20.         include     stdlib.a    ;Links into the UCR Standard
  21.         includelib    stdlib.lib    ; Library package.
  22. ;
  23. ;
  24. dseg        segment    para public 'data'
  25. ;
  26. WordCount    dw    0        ;Holds file word count value
  27. LineCnt        dw    0        ;Holds # of lines in file
  28. ControlCnt    dw    0        ;Counts # of control characters
  29. Punct        dw      0        ;Counts # of punctuation characters
  30. AlphaCnt    dw    0        ;Counts # of alphabetic characters
  31. NumericCnt    dw    0        ;Counts numeric digits in file
  32. Other        dw    0        ;Counts other chars in file
  33. MemorySize    dw    0        ;# of paragraphs of free memory
  34. Chars        dw    0        ;Total number of chars in file
  35. TotalChars    dq    0.0        ;FP version of the above
  36. FileHandle    dw    0        ;STDLIB file handle
  37. Const100    dd    100.0
  38. ;
  39. ;
  40. ; Create some sets to use in this program:
  41. ;
  42.         set    CharSet,Alphabetic,Punctuation,Control
  43. ;
  44. ;
  45. ; Character Counter array.  CharCnt [ch] contains the number of "ch"
  46. ; characters appearing in the file.
  47. ;
  48. CharCnt        dw    256 dup (0)
  49. ;
  50. ; Boolean flag to denote in/not in a word:
  51. ;
  52. InWord        db    0
  53. ;
  54. dseg        ends
  55. ;
  56. ;
  57. cseg        segment    para public 'code'
  58.         assume    cs:cseg, ds:dseg
  59. ;
  60. ;
  61. ; LESI is a macro which loads a 32-bit immediate value into ES:DI.
  62. ;
  63. lesi        macro    adrs
  64.         mov     di, seg adrs
  65.         mov    es, di
  66.         lea    di, adrs
  67.         endm
  68. ;
  69. ; ldxi loads a 32-bit immediate value into dx:si:
  70. ;
  71. ldxi        macro    adrs
  72.         mov     dx, seg adrs
  73.         lea    si, adrs
  74.         endm
  75. ;
  76. ;
  77. ;
  78. ;
  79. ; Some useful constants-
  80. ;
  81. cr        equ    13
  82. lf        equ    10
  83. EOFError    equ    8
  84. ;
  85. ;
  86.         public    PSP        ;DOS Program Segment Prefix
  87. PSP        dw    ?        ;Needed by StdLib MemInit routine
  88. ;
  89. ;
  90. ; Okay, here's the main program which does the job:
  91. ;
  92. TS        proc
  93.         mov    cs:PSP, es        ;Save pgm seg prefix
  94.         mov    ax, seg dseg        ;Set up the segment registers
  95.         mov    ds, ax
  96.         mov    es, ax
  97. ;
  98. ; Initialize the memory manager, giving all free memory to the heap.
  99. ;
  100.         mov    dx, 0
  101.         meminit
  102.         mov    MemorySize, cx        ;Save # of available paragraphs.
  103. ;
  104. ; Set up the character sets:
  105. ;
  106. ;  First, build the Alphabetic set:
  107. ;
  108.         mov    al, "A"
  109.         mov    ah, "Z"
  110.         lesi    Alphabetic
  111.         RangeSet
  112.         AddStrL
  113.         db    "abcdefghijklmnopqrstuvwxyz",0
  114. ;
  115. ; Create the set with the punctuation characters:
  116. ;
  117.         lesi    Punctuation
  118.         AddStrL
  119.         db    "!@#$%^&*()_-+={[}]|\':;<,>.?/~`", '"', 0
  120. ;
  121. ; Create the control character set:
  122. ;
  123.         lesi    Control
  124.         mov    al,0
  125.         mov    ah, 1fh
  126.         RangeSet
  127.         mov    al, 7fh
  128.         AddChar
  129. ;
  130. ;
  131. ; Print the amount of available memory.
  132. ;
  133.         printf
  134.         db    "Text Statistics Program",cr,lf
  135.         db    "There are %d paragraphs of memory available",cr,lf,0
  136.         dd    MemorySize
  137. ;
  138. ; Get the filename off the command line:
  139. ;
  140.         argc
  141.         cmp    cx, 1
  142.         je    GoodCmdLine
  143.         print
  144.         db    cr,lf
  145.         db    "Missing file name!",cr,lf
  146.         db    "Usage: TS <filename>",cr,lf,0
  147.         jmp    Return2DOS
  148. ;
  149. GoodCmdLine:    mov    ax, 1
  150.         argv                ;Get the filename.
  151. ;
  152. ; Open the file.
  153. ;
  154.         mov    al, 0            ;Open for reading.
  155.         fopen                ;Open the file.
  156.         jnc    GoodOpen
  157. ;
  158. ; If the carry flag comes back set, we've got an error, print an appropriate
  159. ; message and quit:
  160. ;
  161.         print
  162.         db    "DOS error #",0
  163.         puti                ;Error code is in AX.
  164.         putcr
  165.         jmp    Return2DOS
  166. ;
  167. ; If the carry flag comes back clear, we've successfully opened the file.
  168. ; AX contains the STDLIB filehandle, ES:DI still points at the filename
  169. ; allocated on the heap:
  170. ;
  171. GoodOpen:    mov    FileHandle, AX        ;Save STDLIB file handle.
  172.         print
  173.         db    "Computing text statistics for ",0
  174.         puts                ;Print filename
  175.         free                ;Dispose of space on heap
  176.         putcr
  177.         putcr
  178. ;
  179. ; The following loops check for transitions between words and delimiters.
  180. ; Each time we go from "not a word" -> "word" this code bumps up the word
  181. ; count by one.
  182. ;
  183.         mov    ax, FileHandle
  184.         fReadOn
  185. ;
  186. TSLoop:        getc
  187.         jnc    NoError
  188.         jmp    ReadError
  189. ;
  190. ; See if the character is alphabetic
  191. ;
  192. NoError:    lesi    Alphabetic         ;Set contains A-Z, a-z
  193.         Member
  194.         jz    NotAlphabetic
  195.         inc    AlphaCnt
  196.         jmp    StatDone
  197. ;
  198. ; See if the character is a digit:
  199. ;
  200. NotAlphabetic:    cmp    al, "0"
  201.         jb    NotNumeric
  202.         cmp    al, "9"
  203.         ja    NotNumeric
  204.         inc    NumericCnt
  205.         jmp    StatDone
  206. ;
  207. ; See if the character is a punctuation character
  208. ;
  209. NotNumeric:    lesi    Punctuation
  210.         Member
  211.         jz    NotPunctuation
  212.         inc    Punct
  213.         jmp    StatDone
  214. ;
  215. ; See if this is a control character:
  216. ;
  217. NotPunctuation:    lesi    Control
  218.         Member
  219.         jz    NotControl
  220.         inc    ControlCnt
  221.         jmp    StatDone
  222. ;
  223. NotControl:    inc    Other
  224. StatDone:       mov    bl, al        ;Use char as index into CharCnt
  225.         mov    bh, 0
  226.         shl    bx, 1        ;Convert word index to byte index
  227.         inc    CharCnt [bx]
  228. ;
  229. ; Count lines and characters here:
  230. ;
  231.         cmp    al, lf
  232.         jne    NotNewLine
  233.         inc    LineCnt
  234. ;
  235. NotNewLine:     inc    Chars
  236. ;
  237. ; Count words down here
  238. ;
  239.         cmp    InWord, 0        ;See if we're in a word.
  240.         je    NotInAWord
  241.         cmp    al, " "
  242.         ja    WCDone
  243.         mov    InWord, 0        ;Just left a word
  244.         jmp    WCDone
  245. ;
  246. NotInAWord:    cmp    al, " "
  247.         jbe    WCDone
  248.         mov    InWord, 1        ;Just entered a word
  249.         inc    WordCount
  250. ;
  251. WCDone:
  252. ;
  253. ; Okay, or the current character into the character set so we can keep
  254. ; track of the characters which appear in this file.
  255. ;
  256.         lesi    CharSet
  257.         AddChar
  258.         jmp    TSLoop
  259. ;
  260. ;
  261. ; Come down here on EOF or other read error.
  262. ;
  263. ReadError:    cmp    ax, EOFError
  264.         je    Quit
  265.         print
  266.         db    "DOS Error ",0
  267.         puti
  268.         putcr
  269.         jmp    Return2DOS
  270. ;
  271. ; Return to DOS.
  272. ;
  273. Quit:        freadoff
  274.         mov    ax, FileHandle
  275.         fclose
  276.         printf
  277.         db    cr,lf,lf
  278.         db    "Number of words in this file is %d",cr,lf
  279.         db    "Number of lines in this file is %d",cr,lf
  280.         db    "Number of control characters is %d",cr,lf
  281.         db    "Number of punctuation characters is %d",cr,lf
  282.         db    "Number of alphabetic characters is %d",cr,lf
  283.         db    "Number of numeric characters is %d",cr,lf
  284.         db    "Number of other characters is %d",cr,lf
  285.         db    "Total number of characters is %d",cr,lf
  286.         db    lf, 0
  287.         dd    WordCount,LineCnt,ControlCnt,Punct
  288.         dd    AlphaCnt,NumericCnt,Other,Chars
  289. ;
  290. ; Print the characters that actually appeared in the file.
  291. ;
  292.         lesi    CharSet
  293. EC64:        mov    cx, 64            ;Chars/line on output.
  294. EachChar:    RmvItem
  295.         cmp    al, 0
  296.         je    CSDone
  297.         cmp    al, " "
  298.         jbe    EachChar
  299.         putc
  300.         loop    EachChar
  301.         putcr
  302.         jmp    EC64
  303. ;
  304. CSDone:        print
  305.         db    cr,lf,lf
  306.         db    "Press any key to continue:",0
  307.         getc
  308.         putcr
  309.         putcr
  310. ;
  311. ; Now print the statistics for each character:
  312. ;
  313.         mov    ax, Chars        ;Get character count,
  314.         utof                ; convert it to a floating
  315.         lesi    TotalChars        ; point value, and save this
  316.         sdfpa                ; value in "TotalChars".
  317. ;
  318. ; Print out each character, the number of occurrences, and the ratio of
  319. ; this character's count to the total number of characters.
  320. ;
  321.         mov    bx, " "*2        ;Start output with spaces.
  322. ComputeRatios:    cmp    CharCnt[bx], 0
  323.         je    SkipThisChar
  324.         mov    ax, bx
  325.         shr    ax, 1            ;Convert index to character
  326.         putc                ; and print it.
  327.         print
  328.         db    " = ",0
  329.         mov    ax, CharCnt [bx]
  330.         mov    cx, 4
  331.         putisize
  332.         print
  333.         db    "  Percentage of total is ",0
  334. ;
  335.         utof
  336. ;
  337. ; Divide by the total number of characters in the file:
  338. ;
  339.         lesi    TotalChars
  340.         ldfpo
  341.         fpdiv
  342. ;
  343. ; Multiply by 100 to get a percentage
  344. ;
  345.         lesi    Const100
  346.         lsfpo
  347.         fpmul
  348. ;
  349. ; Print the ratio:
  350. ;
  351.         mov    al, 7
  352.         mov    ah, 3
  353.         ftoam
  354.         puts
  355.         free
  356.         print
  357.         db    "%   ",cr,lf,0
  358. ;
  359. SkipThisChar:    inc    bx
  360.         inc    bx
  361.         cmp    bx, 200h
  362.         jb      ComputeRatios
  363.         putcr
  364. ;
  365. Return2DOS:    mov     ah, 4ch
  366.         int     21h
  367. ;
  368. ;
  369. TS        endp
  370. ;
  371. ;
  372. ;
  373. cseg            ends
  374. ;
  375. ;
  376. ; Allocate a reasonable amount of space for the stack (2k).
  377. ;
  378. sseg        segment    para stack 'stack'
  379. stk        db    256 dup ("stack   ")
  380. sseg        ends
  381. ;
  382. ;
  383. ;
  384. ; zzzzzzseg must be the last segment that gets loaded into memory!
  385. ; The UCR Standard Library package uses this segment to determine where
  386. ; the end of the program lies.
  387. ;
  388. zzzzzzseg    segment    para public 'zzzzzz'
  389. LastBytes    db    16 dup (?)
  390. zzzzzzseg    ends
  391.         end    TS
  392.